﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ModBot.ConfigBuilder.Providers
{
    public class BuffSettingsProvider
    {
        private ModBotSettingsProvider parentProvider;
        public List<BuffSettingInstanceProvider> BuffSettingInstances;

        #region Public Properties

        /// <summary>
        /// Gets the number of buff options configured
        /// </summary>
        public int ABCount { get; set; }

        /// <summary>
        /// Gets or sets the interval in seconds to check for buffs.
        /// </summary>
        public int ABCheckTime { get; set; }

        /// <summary>
        /// Gets or sets the maximum number of targets to track for buffs.
        /// This value should not include pets.
        /// </summary>
        public int ABMobMax { get; set; }


        #endregion

        private BuffSettingsProvider() { }
        public BuffSettingsProvider(ModBotSettingsProvider parentProvider)
        {
            this.parentProvider = parentProvider;
            BuffSettingInstances = new List<BuffSettingInstanceProvider>();
        }

        public override string ToString()
        {
            #region Format String
            string formatString =
                "[AdvBuff]\r\n" +
                "ABCount={0}\r\n" +
                "ABCheckTime={1}\r\n" +
                "ABMobMax={2}\r\n\r\n";


            #endregion


            string output = string.Format(formatString,
                ABCount,
                ABCheckTime,
                ABMobMax);

            foreach (BuffSettingInstanceProvider provider in this.BuffSettingInstances)
            {
                output += provider.ToString();
            }


            return output;
        }

        public static BuffSettingsProvider LoadFromINI(ModBotSettingsProvider settingsProvider, string filepath)
        {
            BuffSettingsProvider provider = new BuffSettingsProvider(settingsProvider);

            try
            {
                provider.ABCount = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffSettings_Key_ABCount), Defaults.Default_BuffSettings_ABCount);
                provider.ABCheckTime = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffSettings_Key_ABCheckTime), Defaults.Default_BuffSettings_ABCheckTime);
                provider.ABMobMax = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffSettings_Key_ABMobMax), Defaults.Default_BuffSettings_ABMobMax);
                               

                provider.BuffSettingInstances.Clear();
                for (int i = 0; i < provider.ABCount; i++)
                {
                    BuffSettingInstanceProvider instance = BuffSettingInstanceProvider.LoadFromINI(provider, i + 1, filepath);
                    provider.BuffSettingInstances.Add(instance);
                }


                if (provider.ABCount != provider.BuffSettingInstances.Count) provider.ABCount = provider.BuffSettingInstances.Count;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return provider;
        }

        public static void SaveToIni(BuffSettingsProvider provider, string filepath)
        {
            IniFileProvider.WriteValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffSettings_Key_ABCount, Convert.ToString(provider.ABCount));
            IniFileProvider.WriteValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffSettings_Key_ABCheckTime, Convert.ToString(provider.ABCheckTime));
            IniFileProvider.WriteValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffSettings_Key_ABMobMax, Convert.ToString(provider.ABMobMax));
            

            for (int i = 0; i < provider.ABCount; i++)
            {
                BuffSettingInstanceProvider.SaveToIni(provider.BuffSettingInstances[i], filepath);
            }
        }
    }

    public class BuffSettingInstanceProvider
    {
        private BuffSettingsProvider settingsProvider;
        /// <summary>
        /// Gets or sets the Gem number, alt, ability, item, script, or potionbelt reference to use
        /// for this buff.
        /// </summary>
        public string ABGem { get; set; }

        /// <summary>
        /// Gets or sets the spell, item, alt, ability, or script name to reference with 
        /// this buff.
        /// </summary>
        public string ABSpell { get; set; }

        /// <summary>
        /// Gets or sets the bandolier set name to swap in before casting the buff.
        /// Please see MQ2Bandolier and MQ2Cast for more information.
        /// </summary>
        public string ABSpellFoci { get; set; }

        /// <summary>
        /// Gets or sets any spell extension percentage.
        /// </summary>
        public int ABDurMod { get; set; }

        /// <summary>
        /// Gets or sets the minimum mana percentage to have before
        /// attempting the buff.
        /// </summary>
        public int ABSpellMinMana { get; set; }

        /// <summary>
        /// Gets or sets the alias for the spell being cast. Note this alias
        /// must be unique and cannot contain spaces.
        /// </summary>
        public string ABSpellAlias { get; set; }

        /// <summary>
        /// Gets or sets the channel to announce the buff or, if left blank
        /// will not announce the buff.
        /// </summary>
        public string ABAnnouce { get; set; }

        /// <summary>
        /// Gets or sets the number of targets that must be 
        /// present before casting the spell.
        /// </summary>
        public Int32 ABTarCnt { get; set; }

        /// <summary>
        /// Gets or sets the class or target list for this buff.
        /// Valid Target Types:
        /// - ShortClassName Used for class specific buffs (ie. haste on "war"). 
        /// - self Used for self only spells.
        /// - grp for Group spells (e.g. ABTarType1=self grp)
        /// - pet used to cast buffs on all pets in the group.
        /// - mypet used to cast on only your pet. Please note that pet and mypet are mutually exclusive.
        /// - cbt for spells to be casted during combat (e.g. an entry for Yaulp would be ABTarType1=self cbt). Please note that any NPC within radius that is not on your exclude list will cause 'cbt' buffs to fire. If you want to buff next to NPCs (and don't plan to kill them), use the exclude command. If you later decide to kill whatever mob you've excluded, use the include command to remove it from list. The macro does not check combat state of the tank for buffs.
        /// - idle used with cbt for spells to be casted when in or out of combat (e.g. if you wanted to keep Yaulp on at all times (in AND out of combat), your entry would be ABTarType1=self cbt idle). Please note that idle is only used in ABTarType when cbt is also used.
        /// - aura used to cast an aura - must be used with self (e.g. ABTarType1=self aura)                
        /// - tank used to cast only on the designated group tank. Tank designation is keyed from either the TankName variable in the setting section (see above) or by setting a toon to Main Tank (Group.Maintank) using the Roles function. 
        /// Please note: tank, self and mypet are meant to be used by themselves. If you want to cast the same buff on yourself, your pet and the tank, create them as seperate buff entries. 
        /// </summary>
        public string ABTarType { get; set; }

        /// <summary>
        /// Gets or sets whether the bot will cast buffs before they fade or after.
        /// </summary>
        public Boolean ABProactive { get; set; }

        /// <summary>
        /// Gets or sets whether the bot will cast buffs using the spell worn off messages from
        /// EQ to know who to cast the buff on. 
        /// True is only really needed for single targets that are NOT in the group and/or on NetBots
        /// </summary>
        public Boolean ABRecast { get; set; }

        /// <summary>
        /// Gets or sets the spell icon to use when it differs from the name of the spell. For example,
        /// the spell Unity of Spirits, when cast has a spell icon of Transcendent Foresight.
        /// Please note that if the name you have in ABSpellIcon doesn't evaluate to a spell name, the 
        /// buff will be skipped. In other words, leave it blank if your spell doesn't need it. 
        /// </summary>
        public string ABSpellIcon { get; set; }

        /// <summary>
        /// Gets or sets the buff group index.
        /// </summary>
        public int Index { get; set; }

        private BuffSettingInstanceProvider() { }

        public BuffSettingInstanceProvider(BuffSettingsProvider settingsProvider, int index)
        {
            this.settingsProvider = settingsProvider;
            this.Index = index;

            this.ABGem = Defaults.Default_BuffInstance_ABGem;
            this.ABSpell = Defaults.Default_BuffInstance_ABSpell;
            this.ABSpellFoci = Defaults.Default_BuffInstance_ABSpellFoci;
            this.ABDurMod = Defaults.Default_BuffInstance_ABDurMod;
            this.ABSpellMinMana = Defaults.Default_BuffInstance_ABSpellMinMana;
            this.ABSpellAlias = Defaults.Default_BuffInstance_ABSpellAlias;
            this.ABAnnouce = Defaults.Default_BuffInstance_ABAnnouce;
            this.ABTarCnt = Defaults.Default_BuffInstance_ABTarCnt;
            this.ABTarType = Defaults.Default_BuffInstance_ABTarType;
            this.ABProactive = Defaults.Default_BuffInstance_ABProactive;
            this.ABRecast = Defaults.Default_BuffInstance_ABRecast;
            this.ABSpellIcon = Defaults.Default_BuffInstance_ABSpellIcon;
        }

        public override string ToString()
        {
            #region Format String
            string formatString =
                SharedLib.CreateSubCommentBlock("Buff Instance " + Index, SharedLib.NewLine, true) +
                "ABGem{0}={1}\r\n" +
                "ABSpell{0}={2}\r\n" +
                "ABSpellFoci{0}={3}\r\n" +
                "ABDurMod{0}={4}\r\n" +
                "ABSpellMinMana{0}={5}\r\n" +
                "ABSpellAlias{0}={6}\r\n" +
                "ABAnnouce{0}={7}\r\n" +
                "ABTarCnt{0}={8}\r\n" +
                "ABTarType{0}={9}\r\n" +
                "ABProactive{0}={10}\r\n" +
                "ABRecast{0}={11}\r\n" +
                "ABSpellIcon{0}={12}\r\n\r\n";

            #endregion


            string output = string.Format(formatString,
                Index,
                ABGem,
                ABSpell,
                ABSpellFoci,
                ABDurMod,
                ABSpellMinMana,
                ABSpellAlias,
                ABAnnouce,
                ABTarCnt,
                ABTarType,
                ABProactive,
                ABRecast,
                ABSpellIcon);

            return output;
        }

        public static BuffSettingInstanceProvider LoadFromINI(BuffSettingsProvider settingsProvider, int index, string filepath)
        {
            BuffSettingInstanceProvider provider = new BuffSettingInstanceProvider(settingsProvider, index);

            try
            {
                provider.ABGem = IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABGem + provider.Index);
                provider.ABSpell = IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpell + provider.Index);
                provider.ABSpellFoci = IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpellFoci + provider.Index);
                provider.ABDurMod = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABDurMod + provider.Index), Defaults.Default_BuffInstance_ABDurMod);
                provider.ABSpellMinMana = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpellMinMana + provider.Index), Defaults.Default_BuffInstance_ABSpellMinMana);
                provider.ABSpellAlias = IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpellAlias + provider.Index);
                provider.ABAnnouce = IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABAnnouce + provider.Index);
                provider.ABTarCnt = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABTarCnt + provider.Index), Defaults.Default_BuffInstance_ABTarCnt);
                provider.ABTarType = IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABTarType + provider.Index);
                provider.ABProactive = SharedLib.ConvertToBoolean(IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABProactive + provider.Index), Defaults.Default_BuffInstance_ABProactive);
                provider.ABRecast = SharedLib.ConvertToBoolean(IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABRecast + provider.Index), Defaults.Default_BuffInstance_ABRecast);
                provider.ABSpellIcon = IniFileProvider.ReadValue(filepath, Keys.BuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpellIcon + provider.Index);
                
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return provider;
        }

        public static void SaveToIni(BuffSettingInstanceProvider provider, string filepath)
        {
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABGem + provider.Index, Convert.ToString(provider.ABGem));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpell + provider.Index, Convert.ToString(provider.ABSpell));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpellFoci + provider.Index, Convert.ToString(provider.ABSpellFoci));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABDurMod + provider.Index, Convert.ToString(provider.ABDurMod));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpellMinMana + provider.Index, Convert.ToString(provider.ABSpellMinMana));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpellAlias + provider.Index, Convert.ToString(provider.ABSpellAlias));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABAnnouce + provider.Index, Convert.ToString(provider.ABAnnouce));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABTarCnt + provider.Index, Convert.ToString(provider.ABTarCnt));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABTarType + provider.Index, Convert.ToString(provider.ABTarType));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABProactive + provider.Index, Convert.ToString(provider.ABProactive));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABRecast + provider.Index, Convert.ToString(provider.ABRecast));
            IniFileProvider.WriteValue(filepath, Keys.DebuffSettings_Section_Key, Keys.BuffInstance_Key_ABSpellIcon + provider.Index, Convert.ToString(provider.ABSpellIcon));
        }
    }
}
